/*
DataBlock.cpp
*/

#include "FileSystem.h"
#include "DataBlock.h"

DataBlock::DataBlock(unsigned int id_loc, FileSystem * fs_loc):
    fs(fs_loc),
    id(id_loc)
{

    Data = (char *)malloc(Settings::BlockSize);

    if(fs->superblock[id] == '\0'){
        //this data block is free, initialize it (so valgrind stops complaining)
        bzero(Data,Settings::BlockSize);
        fs->write(this, 0, Settings::BlockSize);
    }else{
        //load the data from the file
        fs->read(this);
    }
}

DataBlock::~DataBlock(){

    free(Data);

}

/*
Desc:
    Reads up to size bytes from 'Data' into buf.
    Starts reading at offsets bytes from the beginning of this block.
Returns:
    the number of bytes that were read
*/
unsigned int DataBlock::Read(unsigned int offset, unsigned int size, char * buf){

    if(offset > Settings::BlockSize-1){
        printf("Error DataBlock::Read - invalid offset (%u) for BlockSize %u\n",offset,Settings::BlockSize);
        return 0;
    }

    if(offset+size-1 > Settings::BlockSize-1){
        //user is trying to read too much from this block
        size = Settings::BlockSize-offset;
    }

    memcpy(buf,Data+offset,size);

    return size;
}

/*
Desc:
    Writes up to size bytes from buf into both 'Data' (stored in memory) and the actual file.
    Starts writing at offsets bytes from the beginning of the block.
Returns:
    The number of bytes that were written.
*/
unsigned int DataBlock::Write(unsigned int offset, unsigned int size, char * buf){

    int r;

    if(offset > Settings::BlockSize-1){
        printf("Error DataBlock::Write - invalid offset (%u) for BlockSize %u\n",offset,Settings::BlockSize);
        return 0;
    }

    if(offset+size-1 > Settings::BlockSize-1){
        //user is trying to write too much from this block
        size = Settings::BlockSize-offset;
    }

    //overwrite Data in memory
    memcpy(Data+offset,buf,size);

    r = fs->write(this, offset, size);

    if(r != 0) return 0;

    return size;
}
